package util

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
)

const (
	internal_error_code = -1
)

func HttpReq(requrl, method string, headers http.Header, queryparams url.Values, body []byte, respone interface{}) (errmsg string, code int, respHeader http.Header, err error) {
	//log.Info("HttpReq==> request [requrl=%s][method=%s][proxy=%s][queryparams=%s][body=%s]", requrl, method, proxy, queryparams.Encode(), string(body))
	//check method correct
	supportMethods := map[string]bool{
		"GET":    true,
		"POST":   true,
		"DELETE": true,
		"PUT":    true,
	}
	v, ok := supportMethods[method]
	if !ok || !v {
		errmsg := "Unsupported http method!"
		return errmsg, internal_error_code, nil, errors.New(errmsg)
	}
	var c http.Client
	c = http.Client{}
	var req *http.Request
	if body != nil {
		req, err = http.NewRequest(method, requrl, bytes.NewBuffer(body))
	} else {
		req, err = http.NewRequest(method, requrl, nil)
	}
	if err != nil {
		return "", internal_error_code, nil, err
	}
	req.Close = true // NOTE this !!
	//add body & headers
	if queryparams != nil {
		req.URL.RawQuery = queryparams.Encode()
	}
	if headers == nil {
		req.Header.Set("Content-Type", "application/json")
	} else {
		req.Header = headers
	}
	//req
	resp, err := c.Do(req)
	if err != nil {
		return "", internal_error_code, nil, err
	}
	//处理 返回的头部数据 resp.Header
	//for k, v := range resp.Header {
	//	fmt.Printf("[key=%s][values=%v]", k, v)
	//}
	result, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", internal_error_code, nil, err
	}
	if resp.StatusCode != 200 && resp.StatusCode != 201 {
		return string(result), resp.StatusCode, resp.Header, errors.New(fmt.Sprintf("[errcode=%d][errmsg=%s]", resp.StatusCode, string(result)))
	}
	// unmarshal to Resp object
	if respone != nil {
		err = json.Unmarshal(result, &respone)
		if err != nil {
			return string(result), resp.StatusCode, resp.Header, err
		}
	}
	errmsg = string(result)
	code = resp.StatusCode
	respHeader = resp.Header
	err = nil
	//log.Debugf(log.RESTSys, "HttpReq==> respone [errmsg=%s][code=%d]", errmsg, code)
	resp.Body.Close()
	resp.Close = true
	return //string(result), resp.StatusCode, resp.Header, nil
}
